package org.jscep.transport.response;

import java.io.IOException;
import java.security.cert.CertStore;
import java.security.cert.X509Certificate;

import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedData;
import org.jscep.util.SignedDataUtils;

/**
 * This class handles responses to <code>GetNextCACert</code> requests.
 */
public class GetNextCaCertResponseHandler implements
	ScepResponseHandler<CertStore> {
    private static final String NEXT_CA_CERT = "application/x-x509-next-ca-cert";
    private final X509Certificate signer;

    /**
     * Creates a new <tt>GetNextCaCertResponseHandler</tt> using the provided certificate.
     * 
     * @param signer the signer of the <tt>signedData</tt> response.
     */
    public GetNextCaCertResponseHandler(X509Certificate signer) {
	this.signer = signer;
    }

    /**
     * {@inheritDoc}
     */
    public CertStore getResponse(byte[] content, String mimeType)
	    throws ContentException {
	if (mimeType.startsWith(NEXT_CA_CERT)) {
	    // http://tools.ietf.org/html/draft-nourse-scep-20#section-4.6.1

	    // The response consists of a SignedData PKCS#7 [RFC2315],
	    // signed by the current CA (or RA) signing key.
	    try {
		CMSSignedData cmsMessageData = new CMSSignedData(content);
		ContentInfo cmsContentInfo = ContentInfo
			.getInstance(cmsMessageData.getEncoded());

		final CMSSignedData sd = new CMSSignedData(cmsContentInfo);
		if (!SignedDataUtils.isSignedBy(sd, signer)) {
		    throw new InvalidContentException("Invalid Signer");
		}
		// The content of the SignedData PKCS#7 [RFC2315] is a
		// degenerate
		// certificates-only Signed-data (Section 3.3) message
		// containing the
		// new CA certificate and any new RA certificates, as defined in
		// Section 5.2.1.1.2, to be used when the current CA certificate
		// expires.
		return SignedDataUtils.fromSignedData(sd);
	    } catch (IOException e) {
		throw new InvalidContentTypeException(e);
	    } catch (CMSException e) {
		throw new InvalidContentTypeException(e);
	    }
	} else {
	    throw new InvalidContentTypeException(mimeType, NEXT_CA_CERT);
	}
    }
}
